package com.example.shiwu.util;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
import android.util.Log;

import androidx.annotation.RequiresApi;

import java.io.File;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;

public class EncryptedFolderHelper {
    private static final String TAG = "EncryptedFolderHelper";
    private static final String KEY_ALIAS = "download_encrypted_folder_key";
    private static final String KEY_STORE_PROVIDER = "AndroidKeyStore";
    private static final String TRANSFORMATION = "AES/GCM/NoPadding";

    private final Context mContext;

    public EncryptedFolderHelper(Context context) {
        this.mContext = context;
    }

    /**
     * 在Download目录下创建加密文件夹
     * @param folderName 文件夹名称
     * @return 文件夹的Uri或路径
     */
    public Object createEncryptedFolder(String folderName) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            return createEncryptedFolderScopedStorage(folderName);
        } else {
            return createEncryptedFolderLegacy(folderName);
        }
    }

    /**
     * Android 10及以上使用分区存储创建加密文件夹
     */
    @RequiresApi(api = Build.VERSION_CODES.Q)
    private Uri createEncryptedFolderScopedStorage(String folderName) {
        ContentResolver resolver = mContext.getContentResolver();
        ContentValues values = new ContentValues();

        values.put(MediaStore.Files.FileColumns.DISPLAY_NAME, folderName);
        values.put(MediaStore.Files.FileColumns.MIME_TYPE, "vnd.android.document/directory");
        values.put(MediaStore.Files.FileColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS + "/" + folderName);
        //values.put(MediaStore.Files.FileColumns.IS_DIRECTORY, true);
        values.put("is_directory",true);

        Uri uri = resolver.insert(MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY), values);

        if (uri != null) {
            Log.d(TAG, "加密文件夹创建成功: " + uri.toString());
            // 这里可以对文件夹内的文件进行加密处理
            initializeEncryptionKey();
        } else {
            Log.e(TAG, "加密文件夹创建失败");
        }

        return uri;
    }

    /**
     * Android 10以下使用传统方式创建加密文件夹
     */
    private String createEncryptedFolderLegacy(String folderName) {
        File downloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
        File encryptedFolder = new File(downloadDir, folderName);

        if (!encryptedFolder.exists()) {
            boolean created = encryptedFolder.mkdirs();
            if (created) {
                Log.d(TAG, "加密文件夹创建成功: " + encryptedFolder.getAbsolutePath());
                // 初始化加密密钥
                initializeEncryptionKey();
                return encryptedFolder.getAbsolutePath();
            } else {
                Log.e(TAG, "加密文件夹创建失败");
                return null;
            }
        } else {
            Log.d(TAG, "加密文件夹已存在: " + encryptedFolder.getAbsolutePath());
            return encryptedFolder.getAbsolutePath();
        }
    }

    /**
     * 初始化加密密钥，存储在AndroidKeyStore中
     */
    private void initializeEncryptionKey() {
        try {
            KeyStore keyStore = KeyStore.getInstance(KEY_STORE_PROVIDER);
            keyStore.load(null);

            // 检查密钥是否已存在
            if (!keyStore.containsAlias(KEY_ALIAS)) {
                KeyGenerator keyGenerator = KeyGenerator.getInstance(
                        KeyProperties.KEY_ALGORITHM_AES, KEY_STORE_PROVIDER);

                KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(
                        KEY_ALIAS,
                        KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                        .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                        .setUserAuthenticationRequired(false); // 如果需要用户验证，可以设置为true

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    builder.setInvalidatedByBiometricEnrollment(false);
                }

                keyGenerator.init(builder.build());
                keyGenerator.generateKey();
                Log.d(TAG, "加密密钥创建成功");
            } else {
                Log.d(TAG, "加密密钥已存在");
            }
        } catch (KeyStoreException | IOException | CertificateException | NoSuchAlgorithmException |
                 NoSuchProviderException | InvalidAlgorithmParameterException e) {
            Log.e(TAG, "初始化加密密钥失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 获取加密Cipher
     */
    public Cipher getEncryptionCipher() throws Exception {
        SecretKey secretKey = getSecretKey();
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        return cipher;
    }

    /**
     * 获取解密Cipher
     */
    public Cipher getDecryptionCipher(byte[] iv) throws Exception {
        SecretKey secretKey = getSecretKey();
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, parameterSpec);
        return cipher;
    }

    /**
     * 从KeyStore获取密钥
     */
    private SecretKey getSecretKey() throws KeyStoreException, NoSuchAlgorithmException,
            UnrecoverableKeyException, CertificateException, IOException {
        KeyStore keyStore = KeyStore.getInstance(KEY_STORE_PROVIDER);
        keyStore.load(null);
        return (SecretKey) keyStore.getKey(KEY_ALIAS, null);
    }
}

